package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.mapper.CartInfoMapper;
import com.atguigu.gmall.cart.service.CartInfoAsyncService;
import com.atguigu.gmall.cart.service.CartInfoService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class CartInfoServiceImpl implements CartInfoService {

    @Autowired
    CartInfoMapper cartInfoMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    ProductFeignClient productFeignClient;

    @Autowired
    CartInfoAsyncService cartInfoAsyncService;

    @Override
    public CartInfo addCart(Long skuId, Integer skuNum) {

        String userId = getUserId();
        String cacheH = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        String cacheHK = skuId.toString();

        //查询缓存
        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(cacheH, cacheHK);
        if (cartInfo != null){
            cartInfo.setSkuNum(cartInfo.getSkuNum()+skuNum);
            cartInfo.setIsChecked(1);
            cartInfoAsyncService.updateById(cartInfo);
        }else {
            //数据库
            cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuNum(skuNum);
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setSkuPrice(skuInfo.getPrice());
            cartInfo.setCartPrice(skuInfo.getPrice());
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfoAsyncService.insert(cartInfo);
        }
        redisTemplate.opsForHash().put(cacheH,cacheHK,cartInfo);

        return cartInfo;
    }

    private String getUserId() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String userId = AuthContextHolder.getUserId(request);
        if (StringUtils.isEmpty(userId)) {
            userId = AuthContextHolder.getUserTempId(request);
        }
        return userId;
    }

    @Override
    public CartInfo toCart(Long skuId) {

        String userId = getUserId();
        String cacheH = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        String cacheHK = skuId.toString();
        return (CartInfo) redisTemplate.opsForHash().get(cacheH, cacheHK);
    }


    //用户状态
    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        if (!StringUtils.isEmpty(userId)) {
            //有临时，后真登录
            if (!StringUtils.isEmpty(userTempId)) {
                return mergeCartList(userId,userTempId);
            }else {
                //有真，无临时
                return getCartList(userId);
            }
        }else {
            //有临时无真
            if (!StringUtils.isEmpty(userTempId)) {
                return getCartList(userTempId);
            }
        }
        //都无
        return null;
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        String userId = getUserId();
        String cacheH = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        String cacheHK = skuId.toString();
        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(cacheH, cacheHK);
        cartInfo.setIsChecked(isChecked);
        redisTemplate.opsForHash().put(cacheH,cacheHK,cartInfo);
        cartInfoAsyncService.updateById(cartInfo);
    }

    @Override
    public List<CartInfo> getCartListChecked(String userId) {
        String cacheH = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cacheH);
        /*cartInfoList.stream().forEach(cartInfo -> {
            cartInfo.setSkuPrice(productFeignClient.getPrice(cartInfo.getSkuId()));
        });*/
        return cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked() == 1).collect(Collectors.toList());
    }


    //购物车数据
    public List<CartInfo> mergeCartList(String userId, String userTempId) {

        List<CartInfo> cartInfoListUserId = getCartList(userId);
        List<CartInfo> cartInfoListUserTempId = getCartList(userTempId);

        String cacheHUserTempId = RedisConst.USER_KEY_PREFIX + userTempId +
                RedisConst.USER_CART_KEY_SUFFIX;
        String cacheHUserId = RedisConst.USER_KEY_PREFIX + userId +
                RedisConst.USER_CART_KEY_SUFFIX;

        if (!CollectionUtils.isEmpty(cartInfoListUserId)) {
            //有真
            if (!CollectionUtils.isEmpty(cartInfoListUserTempId)) {
                //真:有临时
                Map<Long, CartInfo> cartInfoMapUserId = cartInfoListUserId.stream().collect(Collectors.toMap(CartInfo::getSkuId, cartInfo -> cartInfo));
                cartInfoListUserTempId.stream().forEach(cartInfoUserTempId ->{
                    CartInfo cartInfoUserId = cartInfoMapUserId.get(cartInfoUserTempId.getSkuId());
                    if (cartInfoUserId != null){
                        //skuId相同
                        cartInfoUserId.setSkuNum(cartInfoUserId.getSkuNum() + cartInfoUserTempId.getSkuNum());
                        cartInfoUserId.setIsChecked(1);
                        //缓存
                        redisTemplate.opsForHash().put(cacheHUserId,cartInfoUserTempId.getSkuId().toString(),cartInfoUserId);
                        //数据库
                        cartInfoAsyncService.updateById(cartInfoUserId);
                    }else {
                        //添加新商品到购物车
                        cartInfoMapUserId.put(cartInfoUserTempId.getSkuId(),cartInfoUserTempId);
                        cartInfoUserTempId.setUserId(userId);
                        //缓存
                        redisTemplate.opsForHash().put(cacheHUserId,cartInfoUserTempId.getSkuId().toString(),cartInfoUserTempId);
                        //数据库
                        cartInfoAsyncService.insert(cartInfoUserTempId);
                    }
                });
            cartInfoAsyncService.deleteById(userTempId);
            redisTemplate.delete(cacheHUserTempId);
            return new ArrayList(cartInfoMapUserId.values());
            }else {
                //真:无临时
                return cartInfoListUserId;
            }
        }else {
            //无真
            if (!CollectionUtils.isEmpty(cartInfoListUserTempId)) {
                //无:有临时

                Map<String, CartInfo> cartInfoMap = cartInfoListUserTempId.stream().map(cartInfo -> {
                    cartInfo.setUserId(userId);
                    return cartInfo;
                }).collect(Collectors.toMap(cartInfo -> cartInfo.getSkuId().toString(), cartInfo -> cartInfo));
                //存入缓存
                redisTemplate.opsForHash().putAll(cacheHUserId,cartInfoMap);
                //异步 数据库
                cartInfoAsyncService.updateByIdExt(userTempId,userId);
                return cartInfoListUserTempId;
            }
        }
        //无真无临时
        return null;
    }

    private List<CartInfo> getCartList(String userId) {
        String cacheH = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;

        return redisTemplate.opsForHash().values(cacheH);
    }

}
